home *** CD-ROM | disk | FTP | other *** search
Wrap
/* VBPRNT32.DLL v2.0 Last Updated 05-29-1996 by Robert Simpson This version designed for 32-bit Windows apps NOTES This version is designed specifically for 32-bit operation, using the expanded DEVMODE structure in Windows 95. The sample programs, DLL files and all source code have been released to the public domain. This DLL was written and compiled in Borland C++ 4.5 */ #include <windows.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <dos.h> #include <ole2.h> #ifdef WIN16 #include <print.h> #include <olenls.h> #include <variant.h> #include <compobj.h> #include <dispatch.h> #endif /* Exported Functions are listed below, here are the proper VB declares: Declare Function VBGetPrinters Lib "vbprnt32.dll" () As String Declare Function VBGetDriverFromName Lib "vbprnt32.dll" (printername As String) As String Declare Function VBSetDefPrinter Lib "vbprnt32.dll" (printername As String) As Integer Declare Function VBGetDefPrinter Lib "vbprnt32.dll" () As String Declare Function VBExtDeviceMode Lib "vbprnt32.dll" (ByVal hWnd As Integer, printername As String, inDev As DEVMODE_TYPE, outDev As DEVMODE_TYPE, ByVal fMode As Integer) As Integer Declare Function VBDevModeToStr Lib "vbprnt32.dll" (inDev As DEVMODE_TYPE) As String Declare Function VBStrToDevMode Lib "vbprnt32.dll" (dmString As String, outDev As DEVMODE_TYPE) As Integer Declare Function VBDeviceCapabilities Lib "vbprnt32.dll" (printername As String, ByVal iCap As Integer, lpStr As Any, inDev As DEVMODE_TYPE) As Long Declare Function VBResetDC Lib "vbprnt32.dll" (ByVal hDC As Integer, outDev As DEVMODE_TYPE) As Integer ' Here is the VB DEVMODE that should be used in all calls to this DLL requiring a DEVMODE structure: Type DEVMODE_TYPE dmDeviceName As String * 32 dmSpecVersion As Integer dmDriverVersion As Integer dmSize As Integer dmDriverExtra As Integer dmFields As Long dmOrientation As Integer dmPaperSize As Integer dmPaperLength As Integer dmPaperWidth As Integer dmScale As Integer dmCopies As Integer dmDefaultSource As Integer dmPrintQuality As Integer dmColor As Integer dmDuplex As Integer dmYResolution As Integer dmTTOption As Integer dmCollate As Integer dmFormName As String * 32 dmLogPixels As Integer dmBitsPerPel As Long dmPelsWidth As Long dmPelsHeight As Long dmDisplayFlags As Long dmDisplayFrequency As Long dmPrivate As String End Type ' The DEVMODE_TYPE structure in VB is essentially a base DEVMODE structure with a dynamic ' string attached to the end (the C version is directly below, named VBDEVMODE) which ' holds the printer's private data (if there is any). */ #define PRINTERLIST 2048 // Size of the buffer that holds the available printers #ifdef WIN32 #define CCONV _stdcall #else #define CCONV FAR PASCAL _export #endif struct VBDEVMODE // The C equivilent to the VB DEVMODE_TYPE structure above { DEVMODE dm; // The size of the DEVMODE structure is larger in Win95 than in Win31 BSTR *dmPrivate; // To compensate for size differences, this dmPrivate area holds the extra data }; // required by Win95 and by the specific printer driver (if it DOES require anything). // Exported functions BSTR CCONV VBGetPrinters(void); BSTR CCONV VBGetDriverFromName(BSTR *printername); short int CCONV VBSetDefPrinter(BSTR *); BSTR CCONV VBGetDefPrinter(void); short int CCONV VBExtDeviceMode(HWND,BSTR *,struct VBDEVMODE *,struct VBDEVMODE *,WORD); BSTR CCONV VBDevModeToStr(struct VBDEVMODE *); short int CCONV VBStrToDevMode(BSTR *,struct VBDEVMODE *); long CCONV VBDeviceCapabilities(BSTR *,WORD,LPSTR,struct VBDEVMODE *); HDC CCONV VBResetDC(HDC, struct VBDEVMODE *); // Internal functions short int GetDriverFromName(BSTR *,LPSTR,LPSTR,LPSTR); DEVMODE *GetVBDevMode(struct VBDEVMODE *); void SetVBDevMode(DEVMODE *,struct VBDEVMODE *); // 16-Bit Windows only #ifdef WIN16 typedef int (FAR PASCAL *ExtDeviceMode)(HWND,HANDLE,LPDEVMODE,LPSTR,LPSTR,LPDEVMODE,LPSTR,WORD); typedef DWORD (FAR PASCAL *DeviceCapabilities)(LPSTR,LPSTR,WORD,LPSTR,LPDEVMODE); #endif /* This function works similar to the VB Dir$() function. The first time it is called, it retrieves the list of installed printers and returns them one at a time to VB. Each call returns the next installed printer. A NULL return value indicates the end of the list. */ BSTR CCONV VBGetPrinters(void) { static short int prevcall; static char printers[PRINTERLIST]; static char buff[256]; char printer[64]; LPSTR driver; LPSTR port; char output[128]; LPSTR port2; if (*printers == 0) { if (prevcall == 1) { prevcall = 0; return 0; } prevcall = 1; memset(printers,0,PRINTERLIST); GetProfileString("devices",NULL,"",printers,PRINTERLIST); } if (buff[0] != 0) { port = strchr(buff,','); if (port == 0) return 0; *port = 0; port ++; strncpy(printer,buff,(int)(port-buff)); printer[(int)(port-buff)] = 0; driver = strchr(port,','); if (driver == 0) return 0; driver[0] = 0; sprintf(output,"%s on %s",printer,port); memmove(buff,driver+1,sizeof buff-(int)(driver-buff)); } else { strcpy(printer,printers); GetProfileString("devices",printer,"",output,sizeof output); strtok(output,","); port = strtok(NULL,","); port2 = strtok(NULL,","); while (port2 != 0) { strcat(buff,printer); strcat(buff,","); strcat(buff,port2); strcat(buff,","); port2 = strtok(NULL,","); } sprintf(output,"%s on %s",printer,port); memmove(printers,printers+strlen(printer)+1,PRINTERLIST-(strlen(printer))); } #ifdef WIN32 return SysAllocStringByteLen(output,strlen(output)); #else return SysAllocStringLen((BSTR)output,strlen(output)); #endif } /* This function returns the printer driver assigned to the specified printer. It's of little use other than reference purposes. The <printername> VB string must follow the format "<printername> on <port>" such as "Epson Stylus COLOR on LPT1:" This is the same format that VBGetPrinters() returns the available printers. */ BSTR CCONV VBGetDriverFromName(BSTR *name) { char pname[80]; char driver[80]; char port[80]; if (GetDriverFromName(name,pname,driver,port) != 0) #ifdef WIN32 return SysAllocStringByteLen(driver,strlen(driver)); #else return SysAllocStringLen((BSTR)driver,strlen(driver)); #endif return 0; } /* Internal function to parse the name of a printer and determine its driver and port. The caller provides pointers for the name, driver and port that this function will fill in */ short int GetDriverFromName(BSTR *name,LPSTR pname,LPSTR pdriver,LPSTR pport) { char printer[128]; LPSTR port; LPSTR driver; char iniprinter[128]; LPSTR found; strcpy(printer,(LPSTR)*name); if (strlen(printer) == 0) return 0; found = strstr(printer," on "); if (found == 0) return 0; *found = 0; GetProfileString("devices",printer,"",iniprinter,sizeof iniprinter); if (iniprinter[0] == 0) return 0; driver = strtok(iniprinter,","); port = found+4; strcpy(pname,printer); strcpy(pdriver,driver); strcpy(pport,port); return -1; } /* Sets the default Windows printer. */ short int CCONV VBSetDefPrinter(BSTR *printer) { char newprinter[128]; char port[32]; char driver[32]; char name[32]; if (GetDriverFromName(printer,name,driver,port) == NULL) return 0; sprintf(newprinter,"%s,%s,%s",name,driver,port); WriteProfileString("windows","device",newprinter); return -1; } /* Gets the default Windows printer from the INI file and parses it */ BSTR CCONV VBGetDefPrinter(void) { LPSTR name; LPSTR port; char inistring[128]; char final[128]; GetProfileString("windows","device","",inistring,sizeof inistring); if (inistring[0] == 0) return 0; name = strtok(inistring,","); strtok(NULL,","); port = strtok(NULL,","); sprintf(final,"%s on %s",name,port); #ifdef WIN32 return SysAllocStringByteLen(final,strlen(final)); #else return SysAllocStringLen((BSTR)final,strlen(final)); #endif } /* Converts a VB DevMode structure to one long string so it can be saved to disk easier. */ BSTR CCONV VBDevModeToStr(struct VBDEVMODE *inmode) { DEVMODE *outmode; int size; BSTR str; size = inmode->dm.dmSize + inmode->dm.dmDriverExtra; if (size < 0) return 0; if (size == 0) size = sizeof(DEVMODE); outmode = GetVBDevMode(inmode); if (outmode == 0) return 0; #ifdef WIN32 str = SysAllocStringByteLen((LPSTR)outmode,size); #else str = SysAllocStringLen((BSTR)outmode,size); #endif free (outmode); return str; } /* Converts a string (hopefully created with the VBDevModeToStr() function) back to a VB DevMode structure */ short int CCONV VBStrToDevMode(BSTR *str,struct VBDEVMODE *outmode) { DEVMODE *inmode; int size; #ifdef WIN32 size = SysStringByteLen(*str); #else size = SysStringLen(*str); #endif if (size < sizeof (DEVMODE)) return 0; inmode = malloc((size_t)size); if (inmode == 0) return 0; memcpy((LPSTR)inmode,(LPSTR)*str,size); SetVBDevMode(inmode,outmode); return -1; } /* Here's the real meat. Calls the printer's ExtDeviceMode function. This one function allows you to bring up the printer's configuration screen, get a copy of the default config, write out a new config and all sorts of other nEeT stuff! */ short int CCONV VBExtDeviceMode(HWND hwnd,BSTR *printername,struct VBDEVMODE *indata,struct VBDEVMODE *outdata,WORD mode) { DEVMODE *realoutput; DEVMODE *indev = 0; char pname[64]; char pdriver[32]; char pport[32]; HANDLE hlib; short int retval; int size; #ifdef WIN16 ExtDeviceMode EDM; #endif if (GetDriverFromName(printername,pname,pdriver,pport) == NULL) return 0; #ifdef WIN32 OpenPrinter(pname,&hlib,NULL); if (hlib == 0) return 0; size = DocumentProperties(hwnd,hlib,pname,NULL,NULL,0); #else strcat(pdriver,".drv"); if ((hlib = LoadLibrary(pdriver)) < 32) return 0; if ((EDM = (ExtDeviceMode)GetProcAddress(hlib,"EXTDEVICEMODE")) == 0) { FreeLibrary(hlib); return 0; } size = EDM(hwnd,hlib,NULL,pname,pport,NULL,NULL,0); #endif if (size != 0) { realoutput = malloc(size); if (indata->dm.dmSize != 0) indev = GetVBDevMode(indata); if (realoutput != 0) { #ifdef WIN32 retval = (short int)DocumentProperties(hwnd,hlib,pname,realoutput,indev,mode); ClosePrinter(hlib); #else retval = EDM(hwnd,hlib,realoutput,pname,pport,indev,NULL,mode); FreeLibrary(hlib); #endif if (retval == 1) SetVBDevMode(realoutput,outdata); return retval; } else { if (size != 0) free(realoutput); if (indev != 0) free(indev); } } return 0; } /* Query the printer device. This function allows you to get information on paper bins, paper sizes, available resolutions and etc from the printer driver. */ long CCONV VBDeviceCapabilities(BSTR *printername,WORD caps,LPSTR output,struct VBDEVMODE *indata) { DEVMODE *indev = 0; HANDLE hlib; char pname[64]; char pdriver[32]; char pport[32]; DWORD retval; LPSTR buffer; LPSTR pos; LPSAFEARRAY array; long lbound,ubound,count,size; #ifdef WIN32 char temp[128]; #else DeviceCapabilities DevCap; #endif if (GetDriverFromName(printername,pname,pdriver,pport) == NULL) return 0; #ifdef WIN32 if (!OpenPrinter(pname,&hlib,NULL)) return 0; ClosePrinter(hlib); #else strcat(pdriver,".drv"); if ((hlib = LoadLibrary(pdriver)) < 32) return 0; if ((DevCap = (DeviceCapabilities)GetProcAddress(hlib,"DEVICECAPABILITIES")) == 0) { FreeLibrary(hlib); return 0; } #endif if (indata->dm.dmSize != 0) indev = GetVBDevMode(indata); if (output != 0 && (caps==DC_BINS||caps==DC_BINNAMES|| caps==DC_ENUMRESOLUTIONS||caps==DC_FILEDEPENDENCIES|| caps==DC_PAPERNAMES||caps==DC_PAPERS||caps==DC_PAPERSIZE)) { memcpy(&array,output,4); size = SafeArrayGetElemsize(array); SafeArrayGetLBound(array,1,&lbound); SafeArrayGetUBound(array,1,&ubound); buffer = malloc((size_t)(size*(ubound-lbound+1))); memset(buffer,0,(size_t)(size*(ubound-lbound+1))); } else buffer = output; #ifdef WIN32 retval = DeviceCapabilities(pname,pport,caps,buffer,indev); #else retval = DevCap(pname,pport,caps,buffer,indev); FreeLibrary(hlib); #endif if (indev != 0) free(indev); if (output != buffer) { pos = buffer; for (count = lbound;count <= ubound;count++) { #ifdef WIN32 if (caps==DC_BINNAMES||caps==DC_FILEDEPENDENCIES||caps==DC_PAPERNAMES) { memset(temp,0,sizeof temp); MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,(LPCSTR)pos,strlen(pos),(LPWSTR)temp,sizeof temp); SafeArrayPutElement(array,&count,temp); pos = pos + size/2; } else #endif { SafeArrayPutElement(array,&count,pos); pos = pos + (int)size; } } free(buffer); } return retval; } HDC CCONV VBResetDC(HDC dc, struct VBDEVMODE *indata) { DEVMODE *indev; HDC retval = 0; if (indata->dm.dmSize == 0) return 0; indev = GetVBDevMode(indata); if (indev != 0) retval = ResetDC(dc,indev); if (indev != 0) free(indev); return retval; } DEVMODE *GetVBDevMode(struct VBDEVMODE *inmode) { DEVMODE *outdevmode; int extra; int size; size = inmode->dm.dmSize + inmode->dm.dmDriverExtra; extra = inmode->dm.dmSize-sizeof(DEVMODE)+inmode->dm.dmDriverExtra; if (size < sizeof(DEVMODE)) { size = sizeof(DEVMODE); extra = 0; } outdevmode = malloc(size); if (outdevmode == 0) return 0; if (extra != 0) memcpy(outdevmode+1,inmode->dmPrivate,extra); memcpy(outdevmode,inmode,sizeof(DEVMODE)); return outdevmode; } void SetVBDevMode(DEVMODE *inmode,struct VBDEVMODE *outmode) { int extra; extra = inmode->dmSize-sizeof(DEVMODE)+inmode->dmDriverExtra; if (extra < 0) extra = 0; memcpy(outmode,inmode,sizeof(DEVMODE)); #ifdef WIN32 SysReAllocStringLen((BSTR *)&outmode->dmPrivate,(BSTR)(inmode+1),extra/2); #else SysReAllocStringLen((BSTR *)&outmode->dmPrivate,(BSTR)(inmode+1),extra); #endif free(inmode); }